//*** The global format data structure(s)
var fmtData      = null;
var digVidData   = null;
var digAudioData = null;

//*** Constants
var MM_PER_INCH = 25.4;
var INCH_PER_MM = 1.0/25.4;

//*** Parameter types
var PT_REAL   = 1;
var PT_SELECT = 2;
var PT_RADIO  = 3;
var PT_BOOL   = 4;
var PT_SELECT_SPLIT = 5;

var TAG2_MASK = 256;

//*** Parameter scaling
var PS_NONE    = 1;
var PS_MEGA    = 1.0e6;
var PS_KILO    = 1.0e3;
var PS_PERCENT = 1.0e-2;
var PS_MILI    = 1.0e-3;
var PS_MICRO   = 1.0e-6;

//*** A debug window
var dbWnd = new DebugWindow();
var edbg  = false; // Enable Debug window

//*** The generator message processing window
var msgWnd = null;
var msgWndParams = "width=300,height=200,status=no,resizable=yes,scrollbars=yes";

//*** The message op-code
var msgOp = "";
var msgTitle = "";

//*** Other "Dialogs"
var digAudioDlg = null;
var digVideoDlg = null;

//*** Are more calculations needed?
var calcMore;

//*** Aspect ratio value mapping table
var arTable = new Array(
  1.0,           // Q-1.00 (1x1 Quadrate)
  1.25,          // G-1.25 (5x4 Graphics)
  (4.0/3.0),     // A-1.33 (4x3 Academy)
  (13.0/9.0),    // B-1.44 (13x9 IMAX)
  (14.0/9.0),    // V-1.56 (14x9 PALplus WSS#2)
  1.60,          // D-1.60 (8x5 VESA CVT)
  (5.0/3.0),     // E-1.67 (5x3 European Film)
  (16.0/9.0),    // H-1.78 (16x9 HDTV)
  (320.0/173.0), // F-1.85 (320x173 US Film)
  2.0,           // U-2.00 (2x1 Univisum)
  (160.0/67.0)   // C-2.39 (160x67 CinemaScope)
);

//*** SCAN mapping table
var scanTable = new Array( 1,  2 );

var asctTable = new Array
(
  2,  // American ORed 
  3,  // American Single Serrated 
  4,  // American Double Serrated (ref SMPTE 170M NTSC) 
  5,  // "Australian" AS 493.1-200X CS serrated
  6,  // European ORed 
  7,  // European Single Serrated 
  8,  // European Double Serrated (ref ITU-R BT.470-6 PAL) 
  9,  // SMPTE 296M-EIA/CEA
  10, // HDTV Single Serrated (ref SMPTE 296M) 
  11, // SMPTE 295M-EIA/CEA
  12, // HDTV Double Serrated (ref SMPTE 295M) 
  14, // SMPTE 274M-EIA/CEA
  15  // HDTV Double Serrated (ref SMPTE 240M, 260M, 274M)
);

var dsctTable = new Array
(
  2,  // American ORed 
  3,  // American Single Serrated 
  4,  // American Double Serrated (ref SMPTE 170M NTSC) 
  5,  // "Australien" AS 493.1-200X CS serrated
  6,  // European ORed 
  7,  // European Single Serrated 
  8   // European Double Serrated (ref ITU-R BT.470-6 PAL) 
);

var dsstTable = new Array
(
  1,  // American Separate 
  3,  // European HDTV Separate
  4,  // Japanese HDTV Separate
  5,  // European Separate 
  6   // Australian AS 4933.1-200X HS & VS
);

var colorModelTable = new Array
(
   3,           // Analog Composite w/Color Kill
   4,           // Analog Composite w/Subcarrier
   1,           // Analog Grayscale YYY
   2,           // Analog Component RGB
   6,           // Analog Component YPbPr SDTV
  11,           // Analog Component YPbPr Betacam
   5,           // Analog Component YPbPr HDTV Legacy
   7,           // Analog Component YPbPr HDTV Modern
   1+TAG2_MASK, // Digital Direct Monochrome
   2+TAG2_MASK, // Digital Direct VI MDA
   5+TAG2_MASK, // Digital Direct RGB
   6+TAG2_MASK, // Digital Direct RGBI CGA
   7+TAG2_MASK, // Digital Direct RrGgBb EGA
   9+TAG2_MASK, // Digital Component YYY
  10+TAG2_MASK, // Digital Component RGB
  13+TAG2_MASK, // Digital Component YCbCr SDTV (ITU-R BT.601-5 Table 3 Item 7)
  14+TAG2_MASK, // Digital Component YCbCr HDTV Legacy (SMPTE 240M)
  15+TAG2_MASK  // Digital Component YCbCr HDTV Modern (ITU-R BT.709-5 Part 1 Section 6.10)
);

var peldTable = new Array
(
    4,
    8,
    32
);

//========================================================
//              The format parameter classes
//========================================================
function NumberParam( name, checkBox, digits, scaleFactor, tag )
{
  this.given       = false;
  this.disabled    = false;
  this.known       = false;
  this.name        = name;
  this.value       = 0;
  this.type        = PT_REAL;
  this.tag         = tag;
  
  this.checkBox    = checkBox;
  this.digits      = digits;
  this.scaleFactor = scaleFactor;
}

function SelectParam( name, valueTable, tag )
{
  this.given      = false;
  this.disabled   = false;
  this.known      = false;
  this.name       = name;
  this.value      = 0;
  this.type       = PT_SELECT;
  this.tag        = tag;
  this.isOptional = false;
  if( arguments.length == 4 ) this.isOptional = arguments[3];

  this.index      = 0;
  this.valueTable = valueTable;
}

function SelectParamSplit( name, valueTable, tag1, tag2 )
{
  this.given      = false;
  this.disabled   = false;
  this.known      = false;
  this.name       = name;
  this.value      = 0;
  this.type       = PT_SELECT_SPLIT;
  this.tag1       = tag1;
  this.tag2       = tag2;

  this.index      = 0;
  this.valueTable = valueTable;
}

function RadioParam( name, tag, isPowerOf2 )
{
  this.given    = false;
  this.disabled = false;
  this.known    = false;
  this.name     = name;
  this.value    = 0;
  this.type     = PT_RADIO;
  this.tag      = tag;
  this.isPowerOf2 = isPowerOf2; // Value is restricted to a power of two
}

function BoolParam( name, tag )
{
  this.type    = PT_BOOL;
  this.name    = name;
  this.checked = false;
  this.tag     = tag;
}

//========================================================
//             The Main format data class
//========================================================
function FmtData()
{
  this.hSizeInch = new NumberParam( "strHsizInch", ckHsizInch, 3, PS_NONE, "HSIZ" );
  this.hSizeMm   = new NumberParam( "strHsizMm",   ckHsizMm,   3, PS_NONE, null   );
  this.vSizeInch = new NumberParam( "strVsizInch", ckVsizInch, 3, PS_NONE, "VSIZ" );
  this.vSizeMm   = new NumberParam( "strVsizMm",   ckVsizMm,   3, PS_NONE, null   );

  this.prat = new NumberParam( "strPrat", ckprat, 3, PS_MEGA, null   );
  this.hrat = new NumberParam( "strHrat", ckhrat, 3, PS_KILO, "HRAT" );
  this.frat = new NumberParam( "strFrat", ckfrat, 3, PS_NONE, null   );
  this.vrat = new NumberParam( "strVrat", ckvrat, 3, PS_NONE, null   );

  this.hres = new NumberParam( "strHres", ckhres, 0, PS_NONE, "HRES" );
  this.hbnk = new NumberParam( "strHbnk", ckhbnk, 0, PS_NONE, null   );
  this.htot = new NumberParam( "strHtot", ckhtot, 0, PS_NONE, "HTOT" );
  
  this.vres = new NumberParam( "strVres", ckvres, 0, PS_NONE, "VRES" );
  this.vbnk = new NumberParam( "strVbnk", ckvbnk, 0, PS_NONE, null   );
  this.vtot = new NumberParam( "strVtot", ckvtot, 0, PS_NONE, "VTOT" );

  this.hresTime = new NumberParam( "strHresTime", ckhresTime, 3, PS_MICRO, null );
  this.hbnkTime = new NumberParam( "strHbnkTime", ckhbnkTime, 3, PS_MICRO, null );
  this.htotTime = new NumberParam( "strHtotTime", ckhtotTime, 3, PS_MICRO, null );

  this.vresTime = new NumberParam( "strVresTime", ckvresTime, 3, PS_MILI, null );
  this.vbnkTime = new NumberParam( "strVbnkTime", ckvbnkTime, 3, PS_MILI, null );
  this.vtotTime = new NumberParam( "strVtotTime", ckvtotTime, 3, PS_MILI, null );

  this.percentbnk = new NumberParam( "strPercentBnk", ckpercentbnk, 1, PS_PERCENT, null );

  this.equb     = new NumberParam( "strEqub",     ckequb,     0, PS_NONE, "EQUB" );
  this.equbTime = new NumberParam( "strEqubTime", ckequbTime, 3, PS_MILI, null  );
  this.equa     = new NumberParam( "strEqua",     ckequa,     0, PS_NONE, "EQUA" );
  this.equaTime = new NumberParam( "strEquaTime", ckequaTime, 3, PS_MILI, null  );

  this.hspd     = new NumberParam( "strHspd",     ckhspd,     0, PS_NONE,  "HSPD" );
  this.hspdTime = new NumberParam( "strHspdTime", ckhspdTime, 3, PS_MICRO, null   );
  this.vspd     = new NumberParam( "strVspd",     ckvspd,     0, PS_NONE,  "VSPD" );
  this.vspdTime = new NumberParam( "strVspdTime", ckvspdTime, 3, PS_MILI,  null   );

  this.hspw     = new NumberParam( "strHspw",     ckhspw,     0, PS_NONE,  "HSPW" );
  this.hspwTime = new NumberParam( "strHspwTime", ckhspwTime, 3, PS_MICRO, null   );
  this.vspw     = new NumberParam( "strVspw",     ckvspw,     0, PS_NONE,  "VSPW" );
  this.vspwTime = new NumberParam( "strVspwTime", ckvspwTime, 3, PS_MILI,  null   );

  this.hbpw     = new NumberParam( "strHbpw",     ckhbpw,     0, PS_NONE,  null  );
  this.hbpwTime = new NumberParam( "strHbpwTime", ckhbpwTime, 3, PS_MICRO, null );

  this.gama = new NumberParam( "strGama", null, 3, PS_NONE, "GAMA" );
  this.avps = new NumberParam( "strAsps", null, 3, PS_NONE, "AVPS" );

  this.dxar = new SelectParam( "aspectRatio", arTable,   null,   true );
  this.scan = new SelectParam( "ScanType",    scanTable, "SCAN", true );
  this.asct = new SelectParam( "acsType",     asctTable, "ASCT", true );
  this.dsct = new SelectParam( "dcsType",     dsctTable, "DSCT" );
  this.dsst = new SelectParam( "dssType",     dsstTable, "DSST" );
  this.peld = new SelectParam( "selPELD",     peldTable,      "PELD", true );
  this.avcs = new SelectParam( "selAVCS",     null,      "AVCS", true );

  this.xvce = new SelectParamSplit( "colorModel",  colorModelTable, "AVST", "DVST" );

  this.ssst = new RadioParam( "sssType", "SSST", true );

  this.squarePel = new BoolParam( "fSquarePixels", null   );
  this.portrait  = new BoolParam( "fPortrait",     null   );
  this.balg      = new BoolParam( "fBalg",         "BALG" );
  this.preg      = new BoolParam( "fPreg",         "PREG" );
  this.rfld      = new BoolParam( "fRfld",         "RFLD" );
  this.equf      = new BoolParam( "fEquf",         "EQUF" );
  this.assgR     = new BoolParam( "fAssgR",        "ASRG" );
  this.assgG     = new BoolParam( "fAssgG",        "ASGG" );
  this.assgB     = new BoolParam( "fAssgB",        "ASBG" );
  this.cspp      = new BoolParam( "fCspp",         "CSPP" );
  this.hspp      = new BoolParam( "fHspp",         "HSPP" );
  this.vspp      = new BoolParam( "fVspp",         "VSPP" );
  this.cspg      = new BoolParam( "fCSPG",         "CSPG" );
  this.hspg      = new BoolParam( "fHSPG",         "HSPG" );
  this.vspg      = new BoolParam( "fVSPG",         "VSPG" );
  this.redg      = new BoolParam( "fREDG",         "REDG" );
  this.grng      = new BoolParam( "fGRNG",         "GRNG" );
  this.blug      = new BoolParam( "fBLUG",         "BLUG" );
  this.pcpg      = new BoolParam( "fPCPG",         "PCPG" );
  this.tspg      = new BoolParam( "fTSPG",         "TSPG" );

  this.avss = new NumberParam( "strAvss", null, 3, PS_NONE, "AVSS" );
  this.asss = new NumberParam( "strAsss", null, 3, PS_NONE, "ASSS" );
  this.hvsa = new NumberParam( "strHVSA", null, 0, PS_NONE, "HVSA" );
  this.hvpd = new NumberParam( "strHVPD", null, 0, PS_NONE, "HVPD" );
}

//========================================================
//                Digital Video Parameters
//========================================================
function DigitalVideoData()
{
  this.dvqm  = new NumberParam( "strDVQM", null, 0, PS_NONE, "DVQM" );
  this.ncpp  = new NumberParam( "strNCPP", null, 0, PS_NONE, "NCPP" );
  this.nbpc  = new NumberParam( "strNBPC", null, 0, PS_NONE, "NBPC" );
  this.nppp  = new NumberParam( "strNPPP", null, 0, PS_NONE, "NPPP" );
  this.ctlm  = new NumberParam( "strCTLM", null, 0, PS_NONE, "CTLM" );
  this.dvic  = new NumberParam( "strDVIC", null, 0, PS_NONE, "DVIC" );
  this.excx  = new NumberParam( "strEXCX", null, 0, PS_NONE, "EXCX" );
  this.sxex  = new NumberParam( "strSXEX", null, 0, PS_NONE, "SXEX" );

  this.dvss  = new NumberParam( "strDVSS", null, 3, PS_NONE, "DVSS" );
  this.cxar  = new NumberParam( "strCXAR", null, 4, PS_NONE, "CXAR" );
  this.exar  = new NumberParam( "strEXAR", null, 4, PS_NONE, "EXAR" );
  this.sxar  = new NumberParam( "strSXAR", null, 4, PS_NONE, "SXAR" );

  this.xlbw  = new NumberParam( "strXLBW", null, 0, PS_NONE, "XLBW" );
  this.xrbw  = new NumberParam( "strXRBW", null, 0, PS_NONE, "XRBW" );
  this.xtbh  = new NumberParam( "strXTBH", null, 0, PS_NONE, "XTBH" );
  this.xbbh  = new NumberParam( "strXBBH", null, 0, PS_NONE, "XBBH" );
  
  this.nlnk = new RadioParam( "selNLNK", "NLNK", false );

  this.dvsm = new SelectParam( "selDVSM", null, "DVSM", true );
  this.dvpt = new SelectParam( "selDVPT", null, "DVPT", true );
}

//========================================================
//              Digital Audio Parameters
//========================================================
function DigitalAudioData()
{
  this.dals  = new NumberParam( "strDALS", null, 0, PS_NONE, "DALS" );
  this.ndas  = new NumberParam( "strNDAS", null, 0, PS_NONE, "NDAS" );
  this.ndac  = new NumberParam( "strNDAC", null, 0, PS_NONE, "NDAC" );
  this.nbpa  = new NumberParam( "strNBPA", null, 0, PS_NONE, "NBPA" );
  this.daxg  = new NumberParam( "strDAXG", null, 0, PS_NONE, "DAXG" );
  this.daxa  = new NumberParam( "strDAXA", null, 0, PS_NONE, "DAXA" );
  this.dadg  = new NumberParam( "strDADG", null, 0, PS_NONE, "DADG" );
  this.daca  = new NumberParam( "strDACA", null, 0, PS_NONE, "DACA" );
  this.dacg  = new NumberParam( "strDACG", null, 0, PS_NONE, "DACG" );
  
  this.arat  = new NumberParam( "strARAT", null, 2, PS_NONE, "ARAT" );

  this.dasi = new SelectParam( "selDASI", null, "DASI" );
  this.dast = new SelectParam( "selDAST", null, "DAST" );
}


/******************************************************************************
*
*  InitializeForm      VER 1.0        03/23/2004
*
*******************************************************************************
*  Program Initialization after the window is completely loaded.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function Initialize()
{
  //*** Uncomment to enable debug output
  dbWnd.Enable( edbg );

  //*** Create the format data structures
  fmtData      = new FmtData();
  digVidData   = new DigitalVideoData();
  digAudioData = new DigitalAudioData();
}


/******************************************************************************
*
*  EvaluateFormat      VER 1.0        03/23/2004
*
*******************************************************************************
*  Evaluate the current format settings.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function EvaluateFormat()
{
  dbWnd.Start();

  //*** Reset all parameters states
  ResetFlags();

  //*** Collect and process the displayed format data
  GatherFormatData();

  //*** Process all the data
  ProcessFormat();

  //*** Update the displayed format data
  UpdateFormData( document.fmtData, fmtData );

  dbWnd.Stop();
}

function ResetFlags()
{
  for( var name in fmtData )
  {
    var param = fmtData[ name ];
    param.known    = false;
    param.disabled = false;
    param.given    = false;
  }
}

function ResetChecks()
{
  for( var name in fmtData )
  {
    var param = fmtData[ name ];
    switch( param.type )
    {
      case PT_REAL:
        if( (param.checkBox != null) && (param.checkBox.enabled == false) )
        {
          ResetParameter( param );
          UpdateParameter( param, document.fmtData );
        }
        break;
    }
  }
}

function ResetAll()
{
  for( var name in fmtData )
  {
    var param = fmtData[ name ];
    ResetParameter( param );
  }

  UpdateFormData( document.fmtData, fmtData );
}

function ResetParameter( param )
{
  param.known    = false;
  param.disabled = false;
  param.given    = false;
  switch( param.type )
  {
    case PT_REAL:
      param.value = 0;
      if( param.checkBox != null )
      {
        param.checkBox.checked = false;
        param.checkBox.enable( true );
      }
      break;

    case PT_SELECT:
    case PT_SELECT_SPLIT:
      param.value = 0;
      break;

    case PT_RADIO:
      param.value = 0;
      break;

    case PT_BOOL:
      param.checked = false;
      break;
  }
}

/******************************************************************************
*
*  GatherFormatData      VER 1.0        03/23/2004
*
*******************************************************************************
*  Gather the format data from the display.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function GatherFormatData()
{
  GatherFormData( document.fmtData, fmtData );
}

function GatherFormData( theForm, theData )
{
  for( var name in theData )
  {
    var param = theData[ name ];

    //*** Get the form element
    var elem = theForm.elements[ param.name ];

    //*** Get its value
    switch( param.type )
    {
      case PT_REAL:
        param.value  = elem.value - 0;
        param.value *= param.scaleFactor;
        param.given = false;
        if( elem.value != "" ) param.given = true;
        /*
        if( param.checkBox != null )
        {
          param.given = param.checkBox.checked;
        }
        */
        break;

      case PT_SELECT:
      case PT_SELECT_SPLIT:
        param.index = elem.selectedIndex;
        param.given = (param.index == 0 ? false : true);
        if( param.given && (param.valueTable != null) )
        {
          param.value = param.valueTable[ param.index - 1 ];
        }
        else
        {
          param.value = param.index;
        }
        break;

      case PT_RADIO:
        param.value = 0;
        for( var i = 0; i < elem.length; i++ )
        {
          if( elem[i].checked )
          {
            param.value = elem[i].value - 0;
          }
        }
        param.given = (param.value == 0 ? false : true);
        break;

      case PT_BOOL:
        param.checked = elem.checked;
        break;

      default:
        param.value = "";
    }
  }
}


/******************************************************************************
*
*  ProcessFormat      VER 1.0        03/23/2004
*
*******************************************************************************
*  Process all the format data until nothing remains to be processed.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function ProcessFormat()
{
  for( var name in fmtData )
  {
    var param = fmtData[ name ];

    if( param.known && param.given )
    {
      param.disabled = true;
    }
    else
    {
      if( param.given )
      {
        param.known = true;
        CalculateFormat();
      }
    }
  }
}


/******************************************************************************
*
*  UpdateFormatData      VER 1.0        03/23/2004
*
*******************************************************************************
*  Update the format data in the display.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function UpdateFormatData()
{
  UpdateFormData( document.fmtData, fmtData );
  if( digAudioDlg != null )
  {
    UpdateFormData( digAudioDlg.document.digAudio, digAudioData );
  }
  if( digVideoDlg != null )
  {
    UpdateFormData( digVideoDlg.document.digVideo, digVidData );
  }
}

function UpdateFormData( theForm, theData )
{
  for( var name in theData )
  {
    var param = theData[ name ];
    UpdateParameter( param, theForm );
  }
}

function UpdateParameter( param, theForm )
{
  //*** Get the form element
  var elem = theForm.elements[ param.name ];

  //*** Set its value
  switch( param.type )
  {
    case PT_REAL:
      if( param.known )
      {
        elem.value = ftoa( param.value/param.scaleFactor, param.digits );
        if( param.checkBox != null )
        {
          param.checkBox.checked = param.given;
          param.checkBox.enable( !param.disabled );
        }
      }
      else
      {
        if( param.checkBox != null )
        {
          param.checkBox.checked = false;
          param.checkBox.enable( true );
          elem.value = "";
        }
        else if( param.given )
        {
          elem.value = ftoa( param.value/param.scaleFactor, param.digits );
        }
      }
      break;

    case PT_SELECT:
    case PT_SELECT_SPLIT:
      if( param.known || param.given )
      {
        elem.selectedIndex = param.index;
      }
      else
      {
        elem.selectedIndex = 0;
      }
      break;

    case PT_RADIO:
      if( param.known || param.given )
      {
        for( var i = 0; i < elem.length; i++ )
        {
          if( param.value == elem[i].value )
          {
            elem[i].checked = true;
            break;
          }
        }
      }
      break;

    case PT_BOOL:
      elem.checked = param.checked;
      break;

    default:
      elem.value = "";
  }
}

/******************************************************************************
*
*  ftoa      VER 1.0        03/23/2004
*
*******************************************************************************
*  Convert an arbitrary double value to a string with the specified number
*  of fractional digits displayed.
*
*******************************************************************************
*
*  Arguments:
*     x          - The double value to be converted.
*     fracDigits - The number of fractional digits.
*                - 0 = none (no decimal point)
*                - Will be padded with zero's as needed.
*
*  Returns:
*     String - The converted string.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function ftoa( x, fracDigits )   
{
  return x.toFixed( fracDigits );
}


/******************************************************************************
*
*  CalculateFormat      VER 1.0        03/23/2004
*
*******************************************************************************
*  Run through all the possible calculations.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  03/23/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function CalculateFormat()
{
  do
  {
    calcMore = false;

    //------------------------------------------------------------------------
    //                          Physical Size
    //------------------------------------------------------------------------
    
    if( (fmtData.hSizeMm.known == false) && fmtData.hSizeInch.known )
    {
      fmtData.hSizeMm.value = fmtData.hSizeInch.value * MM_PER_INCH;
      ParamDone( fmtData.hSizeMm );
    }

    if( (fmtData.hSizeInch.known == false) && fmtData.hSizeMm.known )
    {
      fmtData.hSizeInch.value = fmtData.hSizeMm.value * INCH_PER_MM; 
      ParamDone( fmtData.hSizeInch );
    }

    if( (fmtData.hSizeInch.known == false) && fmtData.dxar.known && fmtData.vSizeInch.known )
    {
      fmtData.hSizeInch.value = fmtData.vSizeInch.value * fmtData.dxar.value;
      ParamDone( fmtData.hSizeInch );
    }

    if( (fmtData.hSizeInch.known == false) && fmtData.hres.known && fmtData.vres.known && fmtData.vSizeInch.known )
    {
      fmtData.hSizeInch.value = fmtData.vSizeInch.value * (fmtData.hres.value / fmtData.vres.value); 
      ParamDone( fmtData.hSizeInch );
    }

    if( (fmtData.vSizeMm.known == false) && fmtData.vSizeInch.known )
    {
      fmtData.vSizeMm.value  = fmtData.vSizeInch.value * MM_PER_INCH;
      ParamDone( fmtData.vSizeMm );
    }

    if( (fmtData.vSizeInch.known == false) && fmtData.vSizeMm.known )
    {
      fmtData.vSizeInch.value = fmtData.vSizeMm.value * INCH_PER_MM; 
      ParamDone( fmtData.vSizeInch );
    }

    if( (fmtData.vSizeInch.known == false) && fmtData.dxar.known && fmtData.hSizeInch.known )
    {
      fmtData.vSizeInch.value = fmtData.hSizeInch.value / fmtData.dxar.value; 
      ParamDone( fmtData.vSizeInch );
    }

    if( (fmtData.vSizeInch.known == false) && fmtData.hres.known && fmtData.vres.known && fmtData.hSizeInch.known )
    {
      fmtData.vSizeInch.value    = fmtData.hSizeInch.value * (fmtData.vres.value / fmtData.hres.value);
      ParamDone( fmtData.vSizeInch );
    }
    
    //------------------------------------------------------------------------
    //                         Pixel Rate
    //------------------------------------------------------------------------
    
    if( (fmtData.prat.known == false) && fmtData.hres.known && fmtData.hresTime.known )
    {
      fmtData.prat.value    = fmtData.hres.value / fmtData.hresTime.value;
      ParamDone( fmtData.prat );
    }
    
    if( (fmtData.prat.known == false) && fmtData.hbnk.known && fmtData.hbnkTime.known )
    {
      fmtData.prat.value  = fmtData.hbnk.value / fmtData.hbnkTime.value;
      ParamDone( fmtData.prat );
    }

    if( (fmtData.prat.known == false) && fmtData.htot.known && fmtData.hrat.known )
    {
      fmtData.prat.value  = fmtData.hrat.value * fmtData.htot.value;
      ParamDone( fmtData.prat );
    }

    if( (fmtData.prat.known == false) && fmtData.htotTime.known && fmtData.htot.known )
    {
      fmtData.prat.value = fmtData.htotTime.value / fmtData.htot.value; 
      ParamDone( fmtData.prat );
    }

    //------------------------------------------------------------------------
    //                          Horizontal Rate 
    //------------------------------------------------------------------------
    
    if( (fmtData.hrat.known == false) && fmtData.htot.known && fmtData.prat.known )
    {
      fmtData.hrat.value = fmtData.prat.value / fmtData.htot.value;
      ParamDone( fmtData.hrat );
    }

    if( (fmtData.hrat.known == false) && fmtData.vresTime.known && fmtData.vres.known )
    {
      fmtData.hrat.value = fmtData.vres.value / fmtData.vresTime.value; 
      ParamDone( fmtData.hrat );
    }

    if( (fmtData.hrat.known == false) && fmtData.vbnkTime.known && fmtData.vbnk.known )
    {
      fmtData.hrat.value = fmtData.vbnk.value / fmtData.vbnkTime.value; 
      ParamDone( fmtData.hrat );
    }

    if( (fmtData.hrat.known == false) && fmtData.frat.known && fmtData.vtot.known )
    {
      fmtData.hrat.value = fmtData.frat.value * fmtData.vtot.value;
      ParamDone( fmtData.hrat );
    }
    
    if( (fmtData.hrat.known == false) && fmtData.htotTime.known )
    {
      fmtData.hrat.value = 1.0 / fmtData.htotTime.value;
      ParamDone( fmtData.Hrat );
    }
    
    //------------------------------------------------------------------------
    //                          Frame Rate
    //------------------------------------------------------------------------
    
    if( (fmtData.frat.known == false) && fmtData.hrat.known && fmtData.vtot.known )
    {
      fmtData.frat.value = fmtData.hrat.value / fmtData.vtot.value;
      ParamDone( fmtData.frat );
    }

    if( (fmtData.frat.known == false) && fmtData.scan.known && fmtData.vrat.known )
    {
      fmtData.frat.value = fmtData.vrat.value / fmtData.scan.value;
      ParamDone( fmtData.frat );
    }

    //------------------------------------------------------------------------
    //                          Vertical Rate
    //------------------------------------------------------------------------
    
    if( (fmtData.vrat.known == false) && fmtData.scan.known && fmtData.frat.known )
    {
      fmtData.vrat.value = fmtData.frat.value * fmtData.scan.value;
      ParamDone( fmtData.vrat );
    }

    //------------------------------------------------------------------------
    //                     Horizontal Resolution
    //------------------------------------------------------------------------
    
    if( (fmtData.hres.known == false) && fmtData.htot.known && fmtData.hbnk.known )
    {
      fmtData.hres.value = fmtData.htot.value - fmtData.hbnk.value;
      ParamDone( fmtData.hres );
    }

    if( (fmtData.hres.known == false) && fmtData.hresTime.known && fmtData.prat.known )
    {
      fmtData.hres.value = fmtData.hresTime.value * fmtData.prat.value; 
      ParamDone( fmtData.hres );
    }

    if( (fmtData.hres.known == false) && fmtData.squarePel.checked && fmtData.vres.known && fmtData.dxar.known )
    {
      fmtData.hres.value = fmtData.vres.value * fmtData.dxar.value; 
      ParamDone( fmtData.hres );
    }

    if( (fmtData.hres.known == false) && fmtData.percentbnk.known && fmtData.hbnk.known )
    {
      fmtData.hres.value = fmtData.hbnk.value * ((1.0 / fmtData.percentbnk.value) - 1.0); 
      ParamDone( fmtData.hres );
    }

    if( (fmtData.hres.known == false) && fmtData.percentbnk.known && fmtData.htot.known )
    {
      fmtData.hres.value = fmtData.htot.value * (1.0 - fmtData.percentbnk.value); 
      ParamDone( fmtData.hres );
    }

    if( (fmtData.hresTime.known == false) && fmtData.hres.known && fmtData.prat.known )
    {
      fmtData.hresTime.value = fmtData.hres.value / fmtData.prat.value; 
      ParamDone( fmtData.hresTime );
    }

    if( (fmtData.hresTime.known == false) && fmtData.htotTime.known && fmtData.hbnkTime.known )
    {
      fmtData.hresTime.value = fmtData.htotTime.value - fmtData.hbnkTime.value; 
      ParamDone( fmtData.hresTime );
    }

    //------------------------------------------------------------------------
    //                       Horizontal Blanking
    //------------------------------------------------------------------------
    
    if( (fmtData.hbnk.known == false) && fmtData.htot.known && fmtData.hres.known )
    {
      fmtData.hbnk.value = fmtData.htot.value - fmtData.hres.value;
      ParamDone( fmtData.hbnk );
    }

    if( (fmtData.hbnk.known == false) && fmtData.hbnkTime.known && fmtData.prat.known )
    {
      fmtData.hbnk.value = fmtData.hbnkTime.value * fmtData.prat.value; 
      ParamDone( fmtData.hbnk );
    }

    if( (fmtData.hbnk.known == false) && fmtData.percentbnk.known && fmtData.hres.known )
    {
      fmtData.hbnk.value = fmtData.hres.value / ((1.0 / fmtData.percentbnk.value) - 1.0); 
      ParamDone( fmtData.hbnk );
    }

    if( (fmtData.hbnk.known == false) && fmtData.percentbnk.known && fmtData.htot.known )
    {
      fmtData.hbnk.value = fmtData.htot.value * fmtData.percentbnk.value;
      ParamDone( fmtData.hbnk );
    }

    if( (fmtData.percentbnk.known == false) && fmtData.hres.known && fmtData.htot.known )
    {
      fmtData.percentbnk.value = 1.0 - (fmtData.hres.value / fmtData.htot.value);
      ParamDone( fmtData.percentbnk );
    }

    if( (fmtData.percentbnk.known == false) && fmtData.hbnk.known && fmtData.htot.known )
    {
      fmtData.percentbnk.value = fmtData.hbnk.value / fmtData.htot.value;
      ParamDone( fmtData.percentbnk );
    }

    if( (fmtData.percentbnk.known == false) && fmtData.hres.known && fmtData.hbnk.known )
    {
      fmtData.percentbnk.value = 1.0 / ((fmtData.hres.value / fmtData.hbnk.value) + 1.0); 
      ParamDone( fmtData.percentbnk );
    }

    if( (fmtData.hbnkTime.known == false) && fmtData.hbnk.known && fmtData.prat.known )
    {
      fmtData.hbnkTime.value = fmtData.hbnk.value / fmtData.prat.value;
      ParamDone( fmtData.hbnkTime );
    }

    if( (fmtData.hbnkTime.known == false) && fmtData.htotTime.known && fmtData.hresTime.known )
    {
      fmtData.hbnkTime.value = fmtData.htotTime.value - fmtData.hresTime.value; 
      ParamDone( fmtData.hbnkTime );
    }

    //------------------------------------------------------------------------
    //                          Horizontal Total
    //------------------------------------------------------------------------
    
    if( (fmtData.htot.known == false) && fmtData.prat.known && fmtData.hrat.known )
    {
      fmtData.htot.value = fmtData.prat.value / fmtData.hrat.value;
      ParamDone( fmtData.htot );
    }

    if( (fmtData.htot.known == false) && fmtData.hres.known && fmtData.hbnk.known )
    {
      fmtData.htot.value = fmtData.hres.value + fmtData.hbnk.value;
      ParamDone( fmtData.htot );
    }

    if( (fmtData.htot.known == false) && fmtData.percentbnk.known && fmtData.hres.known )
    {
      fmtData.htot.value = fmtData.hres.value / (1.0 - fmtData.percentbnk.value); 
      ParamDone( fmtData.htot );
    }

    if( (fmtData.htot.known == false) && fmtData.percentbnk.known && fmtData.hbnk.known )
    {
      fmtData.htot.value = fmtData.hbnk.value / fmtData.percentbnk.value;
      ParamDone( fmtData.htot );
    }

    if( (fmtData.htotTime.known == false) && fmtData.hrat.known )
    {
      fmtData.htotTime.value = 1.0 / fmtData.hrat.value;
      ParamDone( fmtData.htotTime );
    }

    if( (fmtData.htotTime.known == false) && fmtData.prat.known && fmtData.htot.known )
    {
      fmtData.htotTime.value = fmtData.htot.value / fmtData.prat.value;
      ParamDone( fmtData.htotTime );
    }

    if( (fmtData.htotTime.known == false) && fmtData.hresTime.known && fmtData.hbnkTime.known )
    {
      fmtData.htotTime.value = fmtData.hresTime.value + fmtData.hbnkTime.value;
      ParamDone( fmtData.htotTime );
    }

    //------------------------------------------------------------------------
    //                       Vertical Resolution
    //------------------------------------------------------------------------
    
    if( (fmtData.vres.known == false) && fmtData.vtot.known && fmtData.vbnk.known )
    {
      fmtData.vres.value = fmtData.vtot.value - fmtData.vbnk.value;
      ParamDone( fmtData.vres );
    }

    if( (fmtData.vres.known == false) && fmtData.vresTime.known && fmtData.hrat.known )
    {
      fmtData.vres.value = fmtData.vresTime.value * fmtData.hrat.value;
      ParamDone( fmtData.vres );
    }

    if( (fmtData.vres.known == false) && fmtData.squarePel.checked && fmtData.hres.known && fmtData.dxar.known )
    {
      fmtData.vres.value = fmtData.hres.value / fmtData.dxar.value;
      ParamDone( fmtData.vres );
    }

    if( (fmtData.vresTime.known == false) && fmtData.vres.known && fmtData.hrat.known )
    {
      fmtData.vresTime.value = fmtData.vres.value / fmtData.hrat.value;
      ParamDone( fmtData.vresTime );
    }

    if( (fmtData.vresTime.known == false) && fmtData.vtotTime.known && fmtData.vbnkTime.known )
    {
      fmtData.vresTime.value = fmtData.vtotTime.value - fmtData.vbnkTime.value;
      ParamDone( fmtData.vresTime );
    }

    //------------------------------------------------------------------------
    //                         Vertical Blanking
    //------------------------------------------------------------------------
    
    if( (fmtData.vbnk.known == false) && fmtData.vtot.known && fmtData.vres.known )
    {
      fmtData.vbnk.value = fmtData.vtot.value - fmtData.vres.value;
      ParamDone( fmtData.vbnk );
    }

    if( (fmtData.vbnk.known == false) && fmtData.vbnkTime.known && fmtData.hrat.known )
    {
      fmtData.vbnk.value = fmtData.vbnkTime.value * fmtData.hrat.value;
      ParamDone( fmtData.vbnk );
    }

    if( (fmtData.vbnkTime.known == false) && fmtData.vbnk.known && fmtData.hrat.known )
    {
      fmtData.vbnkTime.value = fmtData.vbnk.value / fmtData.hrat.value;
      ParamDone( fmtData.vbnkTime );
    }

    if( (fmtData.vbnkTime.known == false) && fmtData.vtotTime.known && fmtData.vresTime.known )
    {
      fmtData.vbnkTime.value = fmtData.vtotTime.value - fmtData.vresTime.value;
      ParamDone( fmtData.vbnkTime );
    }

    //------------------------------------------------------------------------
    //                            Vertical Total
    //------------------------------------------------------------------------
    
    if( (fmtData.vtot.known == false) && fmtData.hrat.known && fmtData.frat.known )
    {
      fmtData.vtot.value = fmtData.hrat.value / fmtData.frat.value;
      ParamDone( fmtData.vtot );
    }

    if( (fmtData.vtot.known == false) && fmtData.vres.known && fmtData.vbnk.known )
    {
      fmtData.vtot.value = fmtData.vres.value + fmtData.vbnk.value;
      ParamDone( fmtData.vtot );
    }

    if( (fmtData.vtotTime.known == false) && fmtData.frat.known )
    {
      fmtData.vtotTime.value = 1.0 / fmtData.frat.value;
      ParamDone( fmtData.vtotTime );
    }

    if( (fmtData.vtotTime.known == false) && fmtData.hrat.known && fmtData.vtot.known )
    {
      fmtData.vtotTime.value = fmtData.vtot.value / fmtData.hrat.value;
      ParamDone( fmtData.vtotTime );
    }

    if( (fmtData.vtotTime.known == false) && fmtData.vresTime.known && fmtData.vbnkTime.known )
    {
      fmtData.vtotTime.value = fmtData.vresTime.value + fmtData.vbnkTime.value;
      ParamDone( fmtData.vtotTime );
    }

    //------------------------------------------------------------------------
    //                         Equalization 
    //------------------------------------------------------------------------
    
    if( (fmtData.equb.known == false) && fmtData.equbTime.known && fmtData.hrat.known )
    {
      fmtData.equb.value = fmtData.equbTime.value * fmtData.hrat.value;
      ParamDone( fmtData.equb );
    }

    if( (fmtData.equbTime.known == false) && fmtData.equb.known && fmtData.hrat.known )
    {
      fmtData.equbTime.value = fmtData.equb.value / fmtData.hrat.value;
      ParamDone( fmtData.equbTime );
    }

    if( (fmtData.equa.known == false) && fmtData.equaTime.known && fmtData.hrat.known )
    {
      fmtData.equa.value = fmtData.equaTime.value * fmtData.hrat.value;
      ParamDone( fmtData.equa );
    }

    if( (fmtData.equaTime.known == false) && fmtData.equb.known && fmtData.hrat.known )
    {
      fmtData.equaTime.value = fmtData.equa.value / fmtData.hrat.value;
      ParamDone( fmtData.equaTime );
    }

    //------------------------------------------------------------------------
    //                Horiz. and Vert. Sync Pulse Delay
    //------------------------------------------------------------------------
    
    if( (fmtData.hspd.known == false) && fmtData.hspdTime.known && fmtData.prat.known )
    {
      fmtData.hspd.value = fmtData.hspdTime.value * fmtData.prat.value;
      ParamDone( fmtData.hspd );
    }

    if( (fmtData.hspdTime.known == false) && fmtData.hspd.known && fmtData.prat.known )
    {
      fmtData.hspdTime.value = fmtData.hspd.value / fmtData.prat.value;
      ParamDone( fmtData.hspdTime );
    }

    if( (fmtData.vspd.known == false) && fmtData.vspdTime.known && fmtData.hrat.known )
    {
      fmtData.vspd.value = fmtData.vspdTime.value * fmtData.hrat.value;
      ParamDone( fmtData.vspd );
    }

    if( (fmtData.vspdTime.known == false) && fmtData.vspd.known && fmtData.hrat.known )
    {
      fmtData.vspdTime.value = fmtData.vspd.value / fmtData.hrat.value; 
      ParamDone( fmtData.vspdTime );
    }

    //------------------------------------------------------------------------
    //                Horiz. and Vert. Sync Pulse Width
    //------------------------------------------------------------------------
    
    if( (fmtData.hspw.known == false) && fmtData.hspwTime.known && fmtData.prat.known )
    {
      fmtData.hspw.value = fmtData.hspwTime.value * fmtData.prat.value;
      ParamDone( fmtData.hspw );
    }

    if( (fmtData.hspwTime.known == false) && fmtData.hspw.known && fmtData.prat.known )
    {
      fmtData.hspwTime.value = fmtData.hspw.value / fmtData.prat.value;
      ParamDone( fmtData.hspwTime );
    }

    if( (fmtData.vspw.known == false) && fmtData.vspwTime.known && fmtData.hrat.known )
    {
      fmtData.vspw.value = fmtData.vspwTime.value * fmtData.hrat.value;
      ParamDone( fmtData.vspw );
    }

    if( (fmtData.vspwTime.known == false) && fmtData.vspw.known && fmtData.hrat.known )
    {
      fmtData.vspwTime.value = fmtData.vspw.value / fmtData.hrat.value;
      ParamDone( fmtData.vspwTime );
    }

    //------------------------------------------------------------------------
    //                       Broad Pulse Width
    //------------------------------------------------------------------------
    
    if( (fmtData.hbpw.known == false) && fmtData.hbpwTime.known && fmtData.prat.known )
    {
      fmtData.hbpw.value = fmtData.hbpwTime.value * fmtData.prat.value;
      ParamDone( fmtData.hbpw );
    }

    if( (fmtData.hbpwTime.known == false) && fmtData.hbpw.known && fmtData.prat.known )
    {
      fmtData.hbpwTime.value = fmtData.hbpw.value / fmtData.prat.value; 
      ParamDone( fmtData.hbpwTime );
    }

    if( (fmtData.hbpw.known == false) && 
        fmtData.asct.known && fmtData.ssst.known && (fmtData.ssst.value & 4) && fmtData.htot.known )
    {
      switch( fmtData.asct.value )
      {
        case 2: // American ORed 
        case 6: // European ORed 
          fmtData.hbpw.value = fmtData.htot.value; 
          ParamDone( fmtData.hbpw );
          break;
      }
    }

    if( (fmtData.hbpw.known == false) && 
        fmtData.asct.known && fmtData.ssst.known && (fmtData.ssst.value & 4) && fmtData.htot.known && fmtData.hspw.known )
    {
      switch( fmtData.asct.value )
      {
        case 3: // American Single 
        case 7: // European Single 
          fmtData.hbpw.value = fmtData.htot.value - fmtData.hspw.value; 
          ParamDone( fmtData.hbpw );
          break;

        case 4: // Americal Double 
        case 8: // European Double 
          fmtData.hbpw.value = (fmtData.htot.value / 2.0) - fmtData.hspw.value; 
          ParamDone( fmtData.hbpw );
          break;
      }
    }

    if( (fmtData.hbpw.known == false) && 
        fmtData.asct.known && (fmtData.asct.value == 15) && 
        fmtData.ssst.known && (fmtData.ssst.v & 4) && 
        fmtData.hspw.known && fmtData.htot.known && fmtData.scan.known && fmtData.hspd.known )
    {
      fmtData.hbpw.value = (fmtData.htot.value / fmtData.scan.value) - (2.0 * fmtData.hspw.value) - fmtData.hspd.value; 
      ParamDone( fmtData.hbpw );
    }

    if( (fmtData.hbpw.known == false) && 
        fmtData.asct.known  && (fmtData.asct.value == 12) && fmtData.ssst.known && (fmtData.ssst.value & 4) && fmtData.htot.known )
    {
      fmtData.hbpw.value = fmtData.htot.value / 4.0; 
      ParamDone( fmtData.hbpw );
    }

    if( (fmtData.hbpw.known == false) && 
        fmtData.asct.known && (fmtData.asct.value == 10) && fmtData.ssst.known && (fmtData.ssst.value & 4) && fmtData.hres.known )
    {
      fmtData.hbpw.value = fmtData.hres.value; 
      ParamDone( fmtData.hbpw );
    }
    
    //------------------------------------------------------------------------
    //                          Gamma Correction
    //------------------------------------------------------------------------
    
    if( (fmtData.gama.known == false) && fmtData.xvce.known )
    {
      fmtData.gama.value = 1.0; 
      ParamDone( fmtData.gama );
    }

    //------------------------------------------------------------------------
    //                 
    //------------------------------------------------------------------------
    
    if( fmtData.hSizeInch.known && fmtData.vSizeInch.known )
    {
      fmtData.portrait.checked = ((fmtData.hSizeInch.value / fmtData.vSizeInch.value) < 1.0) ? true : false;
      //if( edbg ) dbWnd.w( "</br>Calculated: Portrait = " + fmtData.portrait.checked );
    }

    if( (fmtData.dxar.known == false) && fmtData.hSizeInch.known && fmtData.vSizeInch.known )
    {
      fmtData.dxar.index = 0;
      fmtData.dxar.value = fmtData.hSizeInch.value / fmtData.vSizeInch.value;
      ParamDone( fmtData.dxar );
    }

    //------------------------------------------------------------------------
    // 
    //------------------------------------------------------------------------
    
    if( (fmtData.scan.known == false) && fmtData.vrat.known && fmtData.frat.known )
    {
      fmtData.scan.index = Math.round( fmtData.vrat.value / fmtData.frat.value );
      fmtData.scan.value = fmtData.scan.index;
      ParamDone( fmtData.scan );
    }

  } while( calcMore )
}

function ParamDone( param )
{
  if( edbg ) dbWnd.w( "</br>Calculated: " + param.name + " = " + param.value );
  param.known    = true;
  param.disabled = true; 
  calcMore++;
}



/******************************************************************************
*
*  SaveFormat      VER 1.0        04/06/2004
*
*******************************************************************************
*  Save the format to the genertor.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  04/06/2004   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function SaveFormat()
{
  //*** Verify that a name has been entered.
  if( document.fmtData.strName.value == "" )
  {
    alert( "A name must be entered before saving." );
    return;
  }
  
  var txt = "Save the format to the generator?";
  txt += "\nThe file name will be: \"" + document.fmtData.strName.value + "\"";
  if( confirm( txt ) == false ) return;

  OpenMsgWindow( "SAVE", "Saving the format " + document.fmtData.strName.value  );
}

function LoadFormat()
{
  //*** A blank name means "Load the current Format"
  OpenMsgWindow( "LOAD", "Loading the format " + document.fmtData.strName.value );
}

function TestFormat()
{
  OpenMsgWindow( "TEST", "Testing the format." );
}

/******************************************************************************
*
*  GetPath/SetPath      VER 1.0        07/14/2005
*
*******************************************************************************
*  Reads or writes the path of the generator's formats.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  07/14/2005   Original version written.......................... J. Stenhouse
*
*******************************************************************************
*/
function GetPath()
{
  OpenMsgWindow( "GETP", "Retrieving the format path." );
}

function SetPath()
{
  //*** Verify that a name has been entered.
  if( document.fmtData.strPath.value == "" )
  {
    alert( "A name must be entered before setting the format path." );
    return;
  }
  
  var txt = "Set the format path of the generator?";
  txt += "\nThe path name will be: \"" + document.fmtData.strPath.value + "\"";
  if( confirm( txt ) == false ) return;

  OpenMsgWindow( "SETP", "Setting the format path to " + document.fmtData.strPath.value  );
}

function OpenMsgWindow( op, title )
{
  //*** Initialize
  if( msgWnd != null )
  {
    msgWnd.close();
    msgWnd = null;
  }

  //*** Start the operation
  msgOp    = op;
  msgTitle = title;
  msgWnd   = window.open( "Messaging.html", "msgWnd", msgWndParams );
}

/******************************************************************************
*
*  GenerateXml      VER 1.0        04/07/2004
*
*******************************************************************************
*  Generate the XML data for the format .
*
*******************************************************************************
*
*  Arguments:
*     readable - fale to eliminate uneeded white space, true to 
*                format for readability
*
*  Returns:
*     string - The XML data.
*
*******************************************************************************
* Revision history:
*
*  04/07/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function GenerateXml( readable )
{
  var xml;

  //*** Generate the header
  xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
  if( readable ) xml += "\r\n";
  xml += "<DATAOBJ>";
  if( readable ) xml += "\r\n  ";
  xml += "<HEADER TYPE=\"FMT\" VERSION=\"1.0\"></HEADER>";
  if( readable ) xml += "\r\n  ";
  xml += "<DATA>";

  //*** Fill in the basic parameter fields
  xml += GenerateXmlFromData( fmtData,      readable );
  xml += GenerateXmlFromData( digVidData,   readable );
  xml += GenerateXmlFromData( digAudioData, readable );

  //*** Generate some other tags
  if( readable ) xml += "\r\n    ";
  xml += "<USIZ>1</USIZ>";

  if( readable ) xml += "\r\n    ";
  xml += "<GAMC>";
  xml += fmtData.gama.known ? "TRUE" : "FALSE";
  xml += "</GAMC>";

  if( readable ) xml += "\r\n    ";
  xml += "<AVPG>";
  xml += fmtData.avps.known ? "TRUE" : "FALSE";
  xml += "</AVPG>";

  //*** Terminate
  if( readable ) xml += "\r\n  ";
  xml += "</DATA>";
  if( readable ) xml += "\r\n";
  xml += "</DATAOBJ>";
  if( readable ) xml += "\r\n";

  if( xml.length > 3072 )
  {
    alert( "Data length to long!" );
    xml = "*** Error ***";
  }

  return xml;
}

function GenerateXmlFromData( theData, readable )
{
  var xml = "";

  for( var name in theData )
  {
    var param = theData[ name ];

    //*** Get its value
    switch( param.type )
    {
      case PT_REAL:
        if( (param.known || param.given) && (param.tag != null) )
        {
          if( readable ) xml += "\r\n    ";
          xml += "<" + param.tag + ">";
          if( param.digits != 0 )
          {
            xml += param.value.toExponential();
          }
          else
          {
            xml += param.value.toFixed(0);
          }
          xml += "</" + param.tag + ">"; 
        }
        break;

      case PT_SELECT:
        if( (param.known || param.given || (param.isOptional == false)) && (param.tag != null) )
        {
          if( readable ) xml += "\r\n    ";
          xml += "<" + param.tag + ">";
          xml += param.value.toFixed(0);
          xml += "</" + param.tag + ">"; 
        }
        break;

      case PT_SELECT_SPLIT:
        if( param.known || param.given )
        {
          var t;
          if( param.value & TAG2_MASK) t = param.tag2;
          else t = param.tag1;
          if( readable ) xml += "\r\n    ";
          xml += "<" + t + ">";
          xml += (param.value & (TAG2_MASK-1)).toFixed(0);
          xml += "</" + t + ">"; 
        }
        break;

      case PT_RADIO:
        if( (param.known || param.given) && (param.tag != null) )
        {
          if( readable ) xml += "\r\n    ";
          xml += "<" + param.tag + ">";
          xml += param.value.toFixed(0);
          xml += "</" + param.tag + ">"; 
        }
        break;

      case PT_BOOL:
        if( param.tag != null )
        {
          if( readable ) xml += "\r\n    ";
          xml += "<" + param.tag + ">";
          if( param.checked )
          {
            xml += "TRUE";
          }
          else
          {
            xml += "FALSE";
          }
          xml += "</" + param.tag + ">"; 
        }
        break;
    }
  }

  return xml;
}

/******************************************************************************
*
*  ParseXml      VER 1.0        04/08/2004
*
*******************************************************************************
*  Parse the given XML data for any format parameters.
*
*******************************************************************************
*
*  Arguments:
*     xmlData - The XML data to search.
*
*  Returns:
*     None.
*
*******************************************************************************
* Revision history:
*
*  04/08/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function ParseXml( xmlData )
{
  //*** Reset all parameters
  ResetAll();

  //*** Fill in the basic parameter fields
  ParseXmlToData( xmlData, fmtData      );
  ParseXmlToData( xmlData, digVidData   );
  ParseXmlToData( xmlData, digAudioData );

  //*** Check for some other items
  value = GetValue( xmlData, "USIZ" );
  if( value != null )
  {
    if( value != "1" )
    {
      //*** Need to use mm instead of inches
      if( fmtData.hSizeInch.given )
      {
        fmtData.hSizeMm.value = fmtData.hSizeInch.value;
        fmtData.hSizeMm.checkBox.checked   = true;
        fmtData.hSizeMm.given = true;
        fmtData.hSizeMm.known = true;

        fmtData.hSizeInch.checkBox.checked = false;
        fmtData.hSizeInch.given = false;
        fmtData.hSizeInch.known = false;
      }

      if( fmtData.vSizeInch.given )
      {
        fmtData.vSizeMm.value = fmtData.vSizeInch.value;
        fmtData.vSizeMm.checkBox.checked   = true;
        fmtData.vSizeMm.given = true;
        fmtData.vSizeMm.known = true;

        fmtData.vSizeInch.checkBox.checked = false;
        fmtData.vSizeInch.given = false;
        fmtData.vSizeInch.known = false;
      }
    }
  }

  value = GetValue( xmlData, "GAMC" );
  var gated  = false;
  var enable = false;
  if( (value != null) && (value == "TRUE") ) gated = true;
  if( gated && fmtData.gama.known )
  {
    enable = true;
  }
  fmtData.gama.given = enable;
  fmtData.gama.known = enable;

  value = GetValue( xmlData, "AVPG" );
  gated  = false;
  enable = false;
  if( (value != null) && (value == "TRUE") ) gated = true;
  if( gated && fmtData.avps.known )
  {
    enable = true;
  }
  fmtData.avps.given = enable;
  fmtData.avps.known = enable;

  //*** Update the display
  UpdateFormatData();

  //*** Re-evaluate
  EvaluateFormat();
}

function ParseXmlToData( xmlData, theData )
{
  var value;
  var value2;
  for( var name in theData )
  {
    var param = theData[ name ];

    if( param.type == PT_SELECT_SPLIT )
    {
      value  = GetValue( xmlData, param.tag1 );
      value2 = GetValue( xmlData, param.tag2 );
      var i1, i2;
      i1 = i2 = 0;
      if( value  != null ) i1 = value - 0;
      if( value2 != null ) i2 = value - 0;
      if( i1 != 0 ) 
      {
        param.given = true;
        param.known = true;
        param.value = i1;
        param.index = FindIndex( i1, param.valueTable );
      }
      else if( i2 != 0 ) 
      {
        param.given = true;
        param.known = true;
        param.value = i2 + TAG2_MASK;
        param.index = FindIndex( i2 + TAG2_MASK, param.valueTable )
      }
    }
    else
    {
      if( param.tag != null )
      {
        value = GetValue( xmlData, param.tag );
        if( value != null )
        {
          param.given = true;
          param.known = true;
          switch( param.type )
          {
            case PT_REAL:
              param.value = value - 0;
              if( param.checkBox != null )
              {
                param.checkBox.checked = true;
              }
              break;

            case PT_SELECT:
              param.value = value - 0;
              if( param.valueTable != null )
                param.index = FindIndex( param.value, param.valueTable );
              else
                param.index = param.value;
              break;

            case PT_RADIO:
              param.value = value - 0;
              if( param.isPowerOf2 )
              {
                //*** Find the first power of 2 greater or equal to the value
                value2 = 1;
                while( value2 < param.value ) value2 *= 2;
                param.value = value2;
              }
              break;

            case PT_BOOL:
              if( value == "TRUE" )
              {
                param.checked = true;
              }
              break;
          }
        }
      }
    }
  }
}

function FindIndex( value, table )
{
  for( var i = 0; i < table.length; i++ )
  {
    if( table[i] == value ) return i + 1;
  }

  return 0;
}

/******************************************************************************
*
*  GetValue      VER 1.0        04/08/2004
*
*******************************************************************************
*  Get the value associated with the specified tag.
*
*******************************************************************************
*
*  Arguments:
*     xmlData - The XML data to search.
*     tag     - The tag name to search for
*
*  Returns:
*     string - The tag value if found, null if not found.
*
*******************************************************************************
* Revision history:
*
*  04/08/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function GetValue( xmlData, tag )
{
  var exp = "<" + tag + ">([^<]+)<";
  var regexp = new RegExp( exp );
  var result = xmlData.match( regexp );
  if( result == null ) return null;
  return result[1];
}

/******************************************************************************
*
*  GetDataName      VER 1.0        04/07/2004
*
*******************************************************************************
*  Get the data name.
*
*******************************************************************************
*
*  Arguments:
*     None.
*
*  Returns:
*     string - The name.
*
*******************************************************************************
* Revision history:
*
*  04/07/04   Original version written.......................... M. Solfisburg
*
*******************************************************************************
*/
function GetDataName()
{
  return document.fmtData.strName.value;
}

function GetPathName()
{
  return document.fmtData.strPath.value;
}

function SetPathName( pathString )
{
  document.fmtData.strPath.value = pathString;
}

function Tune()
{
  alert( "Feature not currently implemented." );
}

function Quantize()
{
  alert( "Feature not currently implemented." );
}

function ShowXml()
{
  var wnd = window.open();
  wnd.document.open( "text/plain" );
  wnd.document.write( GenerateXml( true ) );
  wnd.document.close();
}

function ShowDigitalAudio()
{
  var params = "width=700,height=400,status=no,resizable=yes,scrollbars=yes";
  if( digAudioDlg == null )
  {
    digAudioDlg = open( "DigitalAudio.html", "digAudioWnd", params, false );
  }
  else
  {
    digAudioDlg.focus();
  }
}

function ShowDigitalVideo()
{
  var params = "width=750,height=500,status=no,resizable=yes,scrollbars=yes";
  if( digVideoDlg == null )
  {
    digVideoDlg = open( "DigitalVideo.html", "digVideoWnd", params, false );
  }
  else
  {
    digVideoDlg.focus();
  }
}

function OnColorModelChange()
{
  var sel = document.fmtData.colorModel.selectedIndex;
  if( sel != 2 )
  {
    document.fmtData.selAVCS.selectedIndex = 0;
  }
}

function OnUnload()
{
  if( digAudioDlg != null ) digAudioDlg.close();
  if( digVideoDlg != null ) digVideoDlg.close();
}
